﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Configuration;
using LinqToLdap;
using LinqToLdap.Collections;

namespace LINQtoLDAPDemo_Model
{
    public class Group
    {
        #region Properties
        public string Name { get; set; }
        public string Description { get; set; }

        /* In order to map to Members property in a group object, this must be a System.Collections.ObjectModel.Collection<string> type.
         * See first example on this page: http://linqtoldap.codeplex.com/wikipage?title=Attribute%20Class%20Map&referringTitle=Mapping
         * */
        // System.Collections.ObjectModel.Collection<string> Members { get; set; }
        public string[] Members { get; set; }

        public string DistinguishedName
        {
            get
            {
                return string.Format("CN={0},CN=Groups,{1}", this.Name, ConfigurationSettings.AppSettings["ldapPartition"]);
            }
            set { }
        }
        #endregion

        public void Update()
        {
            using (var ldapContext = ConfiguredDirectoryContext.DirectoryContext)
            {
                ldapContext.Update<Group>(this);
            }
        }

        public override string ToString()
        {
            return this.Name;
        }

        public static Group[] GetAllGroups()
        {
            using (var ldapContext = ConfiguredDirectoryContext.DirectoryContext)
            {
                Group[] allGroups = ldapContext.Query<Group>().ToArray();
                return allGroups;
            }
        }

        public static List<ILdapPage<User>> GetUserPagesByGroupMembershipStatus(Group _group, int pageSize, bool _isMember)
        {
            using (var ldapContext = ConfiguredDirectoryContext.DirectoryContext)
            {
                List<ILdapPage<User>> allGroupMembers = new List<ILdapPage<User>>();
                LinqToLdap.Collections.ILdapPage<User> currentPage = null;

                string[] nonGroupMemberDNs;
                if (!_isMember)
                {
                    nonGroupMemberDNs = ldapContext.Query<User>().ToArray().Where(u => !_group.Members.Contains(u.DistinguishedName)).Select(u => u.DistinguishedName).ToArray();
                }
                else
                {
                    nonGroupMemberDNs = null;
                }

                do
                {
                    if (currentPage == null)
                    {
                        if (_isMember)
                        {
                            if (_group.Members.Count() > 0)
                            {
                                currentPage = ldapContext.Query<User>().Where(u => _group.Members.Contains(u.DistinguishedName)).OrderBy(u => u.DisplayName).ToPage(pageSize);
                            }
                            else
                            {
                                // Get empty page
                                currentPage = ldapContext.Query<User>().Where(u => u.DistinguishedName.Equals("no matchy!")).OrderBy(u => u.DisplayName).ToPage(pageSize);
                            }
                        }
                        else
                        {
                            if (nonGroupMemberDNs.Count() > 0)
                            {
                                currentPage = ldapContext.Query<User>().Where(u => nonGroupMemberDNs.Contains(u.DistinguishedName)).OrderBy(u => u.DisplayName).ToPage(pageSize);
                            }
                            else
                            {
                                // Get empty page
                                currentPage = ldapContext.Query<User>().Where(u => u.DistinguishedName.Equals("no matchy!")).OrderBy(u => u.DisplayName).ToPage(pageSize);
                            }
                        }
                    }
                    else
                    {
                        if (_isMember)
                        {
                            currentPage = ldapContext.Query<User>().Where(u => _group.Members.Contains(u.DistinguishedName)).OrderBy(u => u.DisplayName).ToPage(currentPage.PageSize, currentPage.NextPage);
                        }
                        else
                        {
                            currentPage = ldapContext.Query<User>().Where(u => nonGroupMemberDNs.Contains(u.DistinguishedName)).OrderBy(u => u.DisplayName).ToPage(currentPage.PageSize, currentPage.NextPage);
                        }
                    }

                    allGroupMembers.Add(currentPage);
                } while (currentPage.HasNextPage);

                return allGroupMembers;
            }
        }
    }
}
